package xyz.lisys.controller;

import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import xyz.lisys.domain.po.CedUserPo;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;

@Slf4j
@Controller
@RequestMapping("/out-parameter")
public class OutParameterController {

    @GetMapping("/param1")
    public String param1() {
        // 返回视图

        return "index";
    }

    @GetMapping("/param2")
    public String param2() {
        // 默认 forward: , 重定向链接

        return "redirect:/";
    }

    @RequestMapping(value = "/param3", method = RequestMethod.GET)
    public ModelAndView param3(ModelAndView view) {
        // RedirectView

        RedirectView redirectView = new RedirectView("/");
        // 是否将重定向URL视为URI模板
        redirectView.setExpandUriTemplateVariables(false);
        // 表示Model属性是否应作为HTTP查询参数公开
        redirectView.setExposeModelAttributes(false);

        view.setView(redirectView);
        return view;
    }

    @GetMapping("/param4")
    public ModelAndView param4(ModelAndView modelAndView) {
        // ModelAndView

        modelAndView.setViewName("index");
        return modelAndView;
    }

    @GetMapping("/param5")
    public ResponseEntity<CedUserPo> param5() {
        // 返回实体类

        CedUserPo cedUser = new CedUserPo();
        cedUser.setId(1);
        cedUser.setName("hello");
        return ResponseEntity.ok(cedUser);
    }

    @GetMapping("/param6")
    public ResponseEntity<FileSystemResource> param6() throws IOException {
        // 返回文件资源

        File imageFile = ResourceUtils
                .getFile(ResourceUtils.CLASSPATH_URL_PREFIX)
                .toPath()
                .resolve("image/avatar.jpg")
                .toFile();

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename(imageFile.getName()).build().toString());
        headers.add(HttpHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE);

        return ResponseEntity.ok()
                .headers(headers)
                .body(new FileSystemResource(imageFile));
    }

    @GetMapping("/param7")
    public ResponseEntity<InputStreamResource> param7() throws IOException {
        // 返回流式资源

        File imageFile = ResourceUtils
                .getFile(ResourceUtils.CLASSPATH_URL_PREFIX)
                .toPath()
                .resolve("image/avatar.jpg")
                .toFile();

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename(imageFile.getName()).build().toString());
        headers.add(HttpHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE);

        return ResponseEntity.ok()
                .headers(headers)
                .body(new InputStreamResource(new FileSystemResource(imageFile).getInputStream()));
    }

    @GetMapping("/param8")
    public void param8(HttpServletResponse response) throws IOException {
        // 返回流式资源 - 编程式

        File imageFile = ResourceUtils
                .getFile(ResourceUtils.CLASSPATH_URL_PREFIX)
                .toPath()
                .resolve("image/avatar.jpg")
                .toFile();

        InputStream inputStream = Files.newInputStream(imageFile.toPath());
        OutputStream outputStream = response.getOutputStream();

        response.setHeader("Content-Disposition", "attachment; filename=\"" + imageFile.getName() + "\"");
        response.setContentType("application/octet-stream");

        byte[] buffer = new byte[4096];
        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, length);
        }

        inputStream.close();
        outputStream.flush();
    }

    @GetMapping(value = "/param9")
    public ResponseEntity<UrlResource> param9() throws IOException {
        // 返回路径资源

        Path imageFilePath = ResourceUtils
                .getFile(ResourceUtils.CLASSPATH_URL_PREFIX)
                .toPath()
                .resolve("image/avatar.jpg")
                .toAbsolutePath();

        UrlResource resource = new UrlResource(imageFilePath.toUri());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(resource.contentLength())
                .body(resource);
    }

    @GetMapping(value = "/param10", produces = {MediaType.APPLICATION_XML_VALUE})
    @ResponseBody
    public CedUserPo param10() {
        // 返回实体类 - XML结果

        CedUserPo user = new CedUserPo();
        user.setId(1);
        user.setName("zyp");
        return user;
    }

    @GetMapping(value = "/param11", produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    public CedUserPo param11() {
        // 返回实体类 - JSON结果

        CedUserPo user = new CedUserPo();
        user.setId(1);
        user.setName("zyp");
        return user;
    }

    @GetMapping(value = "/param12")
    public void param12(HttpServletResponse resp) throws IOException {
        // 流式返回结果

        File imageFile = ResourceUtils
                .getFile(ResourceUtils.CLASSPATH_URL_PREFIX)
                .toPath()
                .resolve("image/avatar.jpg")
                .toFile();

        val out = resp.getOutputStream();
        val in = Files.newInputStream(imageFile.toPath());
        resp.setContentType(MediaType.IMAGE_JPEG_VALUE);
        IOUtils.copy(in, out);
        IOUtils.closeQuietly(in);
        out.flush();
    }
}


